package cn.xjfcloud.onedriveserver.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.xjfcloud.onedriveserver.pojo.dto.ApiConfig;
import cn.xjfcloud.onedriveserver.pojo.dto.CommonConfig;
import cn.xjfcloud.onedriveserver.pojo.dto.OnedriveFileInfo;
import cn.xjfcloud.onedriveserver.pojo.dto.UploadInfo;
import cn.xjfcloud.onedriveserver.service.ApiConfigService;
import cn.xjfcloud.onedriveserver.service.UploadFileService;
import cn.xjfcloud.onedriveserver.util.ApiUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Api
@RestController
public class UploadFileController {

	private static final CommonConfig COMMON_CONFIG = new CommonConfig();

	@Autowired
	private UploadFileService uploadFileService;
	@Autowired
	private ApiConfigService apiConfigService;

	private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
	private static final Logger LOG = LoggerFactory.getLogger(UploadFileController.class);

	/**
	 * 获取上传session（URL）
	 * 
	 * @param filePath
	 * @param fileName
	 * @return
	 */
	@ApiOperation(value = " 获取上传session（URL）", notes = " 获取上传session（URL）")
	@GetMapping("getUploadSession")
	public Map<String, Object> getUploadSession(
			@ApiParam(value = "onedrive的目录", name = "remoteFileDir") String remoteFileDir,
			@ApiParam(value = "文件名", name = "remoteFileName") String remoteFileName,
			@ApiParam(value = "apiConfigd的id", name = "apiConfigId") Integer apiConfigId) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if (apiConfigService.makeTokenUseful(apiConfigId) == 0) {
			resultMap.put("code", "10001");
			resultMap.put("msg", "token not avilable");
			return resultMap;
		}
		String fileId = UUID.randomUUID().toString().replaceAll("-", "");
		try {
			Map<String, Object> sessionMap = uploadFileService.getUploadSession(remoteFileDir, fileId, apiConfigId, true);
			if (null == sessionMap.get("error") || "".equals(sessionMap.get("error"))) {
				// 获取成功
				resultMap.put("code", "0");
				String uploadSession = (String) sessionMap.get("uploadUrl");
				String dateString = (String) sessionMap.get("expirationDateTime");
				SimpleDateFormat dateUTCFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(dateUTCFormat.parse(dateString));
				calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) + 8);
				SimpleDateFormat dateBJFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
				resultMap.put("expire", dateBJFormat.format(calendar.getTime()));
				// 存入数据库
				// uploadInfo
				UploadInfo uploadInfo = new UploadInfo();
				String uploadId = UUID.randomUUID().toString().replaceAll("-", "");
				uploadInfo.setUploadId(uploadId);
				uploadInfo.setUploadSession(uploadSession);
				uploadInfo.setUploadTime(new Date());
				uploadInfo.setOffset(0L);
				uploadInfo.setApiConfigId(apiConfigId);
				uploadFileService.addUploadInfo(uploadInfo);
				// onedriveFileInfo
				OnedriveFileInfo onedriveFileInfo = new OnedriveFileInfo();
				onedriveFileInfo.setFileId(fileId);
				onedriveFileInfo.setOnedrivePath(remoteFileDir + fileId);
				onedriveFileInfo.setUploadId(uploadId);
				onedriveFileInfo.setFileName(remoteFileName);
				onedriveFileInfo.setApiConfigId(apiConfigId);
				uploadFileService.addOnedriveFileInfo(onedriveFileInfo);
				resultMap.put("fileId", fileId);
			} else {
				resultMap.put("code", "10002");
				resultMap.put("msg", sessionMap.get("error"));
				LOG.info("error" + sessionMap.toString());
			}
			return resultMap;
		} catch (IOException | ParseException e) {
			LOG.error("getUploadSession--->", e);
			resultMap.put("code", "10003");
			resultMap.put("msg", "some exception");
			return resultMap;
		}
	}

	/**
	 * 上传文件
	 * 
	 * @param path
	 * @return 任务号uploadId
	 */
	@ApiOperation(value = "上传文件和重新上传", notes = "上传文件和重新上传")
	@PostMapping("uploadFile")
	public Map<String, Object> uploadFile(@ApiParam(value = "服务器文件地址", name = "path", required = false) String path,
			@ApiParam(value = "获取uplaodSession时的fileId", name = "fileId") String fileId) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			OnedriveFileInfo onedriveFileInfo = uploadFileService.getOnedriveFileInfoByFileId(fileId);
			String uploadId = onedriveFileInfo.getUploadId();
			UploadInfo uploadInfo = uploadFileService.getUploadInfoByUploadId(uploadId);
			if (uploadInfo.getOffset() > 0) {
				path = COMMON_CONFIG.getRootFilePath() + onedriveFileInfo.getFileName();
				uploadFileService.uploadFile(path, uploadId);
				resultMap.put("code", "0");
				resultMap.put("uploadId", uploadId);
				return resultMap;
			}else {
				File file = new File(path);
				if (file.exists() == false) {
					resultMap.put("code", "10001");
					resultMap.put("msg", "file not exit!");
					return resultMap;
				} else {
					uploadFileService.uploadFile(path, uploadId);
					resultMap.put("code", "0");
					resultMap.put("uploadId", uploadId);
					return resultMap;
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			LOG.error("UploadFileController:", e);
		} catch (IOException e) {
			e.printStackTrace();
			LOG.error("UploadFileController:", e);
		}
		resultMap.put("code", "10002");
		resultMap.put("msg", "upload fail");
		return resultMap;

	}

	/**
	 * 获取上传状态
	 * 
	 * @param uploadId
	 * @return
	 */
	@ApiOperation(value = " 获取上传状态", notes = " 获取上传状态")
	@GetMapping("getUploadStatus/{uploadId}")
	public Map<String, Object> getUploadStatus(
			@ApiParam(value = "上传文件时返回的uploadId") @PathVariable("uploadId") String uploadId,Integer pageNum, Integer pageSize) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if(uploadId.equals("0")) {
			if(pageNum == null || pageSize == null || pageNum <= 0 || pageSize <= 0) {
				pageNum = 1;
				pageSize = 10;
			}
			PageHelper.startPage(pageNum, pageSize);
			List<Map<String, String>> allUploadingFileInfo = uploadFileService.getAllUploadingFileInfo();
			PageInfo<Map<String, String>> pageInfo = new PageInfo<Map<String, String>>(allUploadingFileInfo);
			resultMap.put("code", "0");
			resultMap.put("uploading", pageInfo.getList());
			resultMap.put("total", pageInfo.getTotal());
			PageHelper.clearPage();
		}else {
			UploadInfo uploadInfo = uploadFileService.getUploadInfoByUploadId(uploadId);
			if (uploadInfo != null) {
				resultMap.put("code", "0");
				resultMap.put("total", uploadInfo.getTotal());
				resultMap.put("offset", uploadInfo.getOffset());
			} else {
				resultMap.put("code", "10001");
				resultMap.put("msg", "uploadId not exits");
			}
		}
		return resultMap;
	}

	/**
	 * 取消上传
	 * @param fileId
	 * @return
	 */
	@ApiOperation(value = "取消上传", notes = "取消上传")
	@RequestMapping("cancelUpload/{fileId}")
	public Map<String, Object> cancelUpload(@ApiParam@PathVariable("fileId")String fileId){
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if(uploadFileService.cancelUpload(fileId)) {
			resultMap.put("code", "0");
			resultMap.put("msg", "cancel upload success");
			return resultMap;
		}else {
			resultMap.put("code", "10001");
			resultMap.put("msg", "cancel upload fail");
			return resultMap;
		}
	}
}
